/**
 * @(#)ChannelRetentServiceImpl.java 2016年11月16日
 * Copyright(C) 2016 ZHEXIN IT CO.,LTD. All rights reserved.
 */
package org.jsbd.boss.service.impl;

import java.math.BigDecimal;
import java.text.ParseException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;

import javax.annotation.Resource;

import org.apache.commons.beanutils.BeanUtils;
import org.apache.commons.lang.StringUtils;
import org.jsbd.boss.common.redis.RedisClient;
import org.jsbd.boss.dao.IDmChannelRetentDAO;
import org.jsbd.boss.domian.ChannelRetentLogInfo;
import org.jsbd.boss.domian.channel.ApkRetentConfig;
import org.jsbd.boss.domian.channel.ApkTaskInfo;
import org.jsbd.boss.domian.channel.ChannelApkConfig;
import org.jsbd.boss.domian.channel.MarkDayTask;
import org.jsbd.boss.domian.channel.RetentTaskVo;
import org.jsbd.boss.domian.channel.TaskQueryVo;
import org.jsbd.boss.domian.channel.WeiboUser;
import org.jsbd.boss.service.IChannelApkInfoService;
import org.jsbd.boss.service.IChannelRetentService;
import org.jsbd.boss.util.CacheKey;
import org.jsbd.boss.util.DateUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;

/**
 *
 *
 * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
 * @version 1.0.0
 */
@Service
public class ChannelRetentServiceImpl implements IChannelRetentService {
	public static final Logger LOGGER = LoggerFactory.getLogger(ChannelRetentServiceImpl.class);

	private static final Map<String, Comparator<ApkTaskInfo>> sortMap = new HashMap<String, Comparator<ApkTaskInfo>>(4);
	static {
		sortMap.put("mobileRate_asc", new ChannelRetentServiceImpl().new MobileRateAscComparator());
		sortMap.put("mobileRate_desc", new ChannelRetentServiceImpl().new MobileRateDescComparator());
		sortMap.put("execRate_asc", new ChannelRetentServiceImpl().new ExecRateAscComparator());
		sortMap.put("execRate_desc", new ChannelRetentServiceImpl().new ExecRateDescComparator());
		sortMap.put("payratio_desc", new ChannelRetentServiceImpl().new ExecRateDescComparator());
		sortMap.put("payratio_desc", new ChannelRetentServiceImpl().new ExecRateDescComparator());
	}
	@Resource
	private IDmChannelRetentDAO dmChannelRetentDAO;
	@Resource
	private IChannelApkInfoService channelApkInfoService;
	@Resource(name = "weiboUserService")
	private ThirdLoginAdapterHandler<WeiboUser> weiboUserService;

	@Resource
	private CacheParamManager cacheParamManager;

	@Resource
	private RedisClient redisClient;

	@Override
	public void deleteUnuseFile(String imsi, String apk, String currentDate) {

		Object paramValue = cacheParamManager.getParamValue(CacheKey.TEST);
		if (paramValue != null && "1".equals(paramValue.toString())) {
			return ;
		}

		RetentTaskVo taskInfo = new RetentTaskVo();
		taskInfo.setImsi(imsi);
		taskInfo.setMark(apk);
		taskInfo.setCurrentDate(currentDate);
		RetentTaskVo retentTaskVo = dmChannelRetentDAO.selectTaskInfo(taskInfo);
		if (retentTaskVo != null && StringUtils.isNotBlank(retentTaskVo.getImsi())) {

			String file1Name = retentTaskVo.getFile1Name();
			if(StringUtils.isNotBlank(file1Name)){
				redisClient.putToQueue(CacheKey.RETENT_DELETE_LIST, file1Name);
			}

			String file2Name = retentTaskVo.getFile2Name();
			if(StringUtils.isNotBlank(file2Name)){
				redisClient.putToQueue(CacheKey.RETENT_DELETE_LIST, file2Name);
			}
			String file3Name = retentTaskVo.getFile3Name();
			if(StringUtils.isNotBlank(file3Name)){
				redisClient.putToQueue(CacheKey.RETENT_DELETE_LIST, file3Name);
			}
			//第四个文件是用户信息 不删除

			String file5Name = retentTaskVo.getFile5Name();
			if(StringUtils.isNotBlank(file5Name)){
				redisClient.putToQueue(CacheKey.RETENT_DELETE_LIST, file5Name);
			}

		}
	}

	/**
	 * selectChannelRetentLogOfDay:查询制定日期的mark留存任务
	 *
	 * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
	 * @param day
	 *            20161115
	 * @return
	 */
	@Override
	public List<ChannelRetentLogInfo> selectChannelRetentLogOfDay(String day) {
		String now = DateUtil.getCurrentDateStr();
		List<ChannelRetentLogInfo> taskList = null;
		String key = CacheKey.R_T_KEY + day;
		taskList = (List<ChannelRetentLogInfo>) redisClient.get(key);
		if (taskList != null) {
			return taskList;
		}
		if (now.equals(day)) {
			ChannelRetentLogInfo channelRetentLogInfo = new ChannelRetentLogInfo();
			channelRetentLogInfo.setCurrentDate(day);
			taskList = dmChannelRetentDAO.selectChannelRetentLogOfDay(channelRetentLogInfo);
			if (taskList != null) {
				redisClient.put(key, taskList, 60);
			}
		} else {
			taskList = (List<ChannelRetentLogInfo>) redisClient.get(key);
			if (taskList == null) {
				ChannelRetentLogInfo channelRetentLogInfo = new ChannelRetentLogInfo();
				channelRetentLogInfo.setCurrentDate(day);
				taskList = dmChannelRetentDAO.selectChannelRetentLogOfDay(channelRetentLogInfo);
				int expireTime = 86400;
				//测试环境缓存5分钟
				Object paramValue = cacheParamManager.getParamValue(CacheKey.TEST);
				if (paramValue != null && "1".equals(paramValue.toString())) {
					expireTime = 300;
				}
				if (taskList != null) {
					redisClient.put(key, taskList, expireTime);
				}
			}
		}
		return taskList;
	}

	@Override
	public Integer updateExecTimesOfDay(String dayStr) {
		return dmChannelRetentDAO.updateExecTimesOfDay(dayStr);
	}

	/**
	 *
	 * getTaskMapOfDay:总量
	 *
	 * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
	 * @param start
	 * @param end
	 * @return
	 */
	private Map<String, ApkTaskInfo> getExecTaskMapOfDay(String start, String end) {
		Map<String, ApkTaskInfo> dayTaskMap = new HashMap<String, ApkTaskInfo>();
		try {
			for (String day : DateUtil.getDatesBetweenTwoDate(start, end).toArray(new String[0])) {
				TaskQueryVo queryVo = new TaskQueryVo();
				queryVo.setCurrentDate(day);
				List<ApkTaskInfo> execList = dmChannelRetentDAO.selectCountRetentTask(queryVo);// 留存已经执行任务总量计算
				for (ApkTaskInfo taskInfo : execList) {
					String tempApk = taskInfo.getMark();
					dayTaskMap.put(tempApk + day + "exectotal", taskInfo);
				}
			}
		} catch (Exception e) {
		}
		return dayTaskMap;
	}

	/**
	 *
	 * getExecTaskMapOfDay:已经执行的量
	 *
	 * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
	 * @param start
	 * @param end
	 * @return
	 */
	public Map<String, ApkTaskInfo> getTaskMapOfDay(String start, String end) {
		Map<String, ApkTaskInfo> dayTaskMap = new HashMap<String, ApkTaskInfo>();
		Set<String> daySet = DateUtil.getDatesBetweenTwoDate(start, end);
		String[] days = daySet.toArray(new String[0]);
		for (String day : days) {
			try {
				TaskQueryVo queryVo = new TaskQueryVo();
				queryVo.setCurrentDate(day);
				List<ApkTaskInfo> totalList = dmChannelRetentDAO.selectCountNewTask(queryVo);
				for (ApkTaskInfo taskInfo : totalList) {
					String tempApk = taskInfo.getMark();
					dayTaskMap.put(tempApk + day + "total", taskInfo);
				}
			} catch (Exception e) {
				LOGGER.error("留存表【{}】不存在", day, e);
			}
		}
		return dayTaskMap;
	}

	/**
	 *
	 * getRetentResultMap:获取留存查询任务
	 *
	 * @author <a href="mailto:xupengcheng@zhexinit.com" >徐鹏程</a>
	 * @param start
	 *            开始日期
	 * @param end
	 * @param apkMap
	 *            apk的留存配置
	 * @param dayTaskMap
	 *            apk天留存任务
	 * @param apkSet
	 * @return
	 */
	private Map<String, ApkTaskInfo> getRetentResultMap(String start, String end, Map<String, Set<ApkRetentConfig>> apkMap, Map<String, ApkTaskInfo> dayTaskMap, Set<String> apkSet) {
		Map<String, ApkTaskInfo> result = new HashMap<String, ApkTaskInfo>();
		String[] retentApks = apkMap.keySet().toArray(new String[0]);
		try {
			for (String apk : retentApks) {
				if (!apkSet.contains(apk)) {
					continue;
				}
				Set<ApkRetentConfig> configList = apkMap.get(apk);
				if (configList != null && configList.size() > 0) {
					for (String day : DateUtil.getDatesBetweenTwoDate(start, end).toArray(new String[0])) {
						String outKey = apk + day;
						ApkTaskInfo resultInfo = result.get(outKey);
						if (resultInfo == null) {
							resultInfo = new ApkTaskInfo();
						}
						for (ApkRetentConfig config : configList) {
							Integer preDay = config.getRetentDay();
							String someDay = DateUtil.getPreDay(preDay, day);
							config.setRetentDate(someDay);
							String innerKey = apk + someDay;
							ApkTaskInfo taskInfoTotal = dayTaskMap.get(innerKey + "total");
							if (taskInfoTotal != null) {
								Double total = taskInfoTotal.getExecTotal() * config.getExetimes() * config.getRetentRate() / 100;
								int tempTotal = resultInfo.getTotal() + total.intValue();
								resultInfo.setTotal(tempTotal);
							}
							resultInfo.setApkName(config.getApkName());
						}
						ApkTaskInfo execTotal = dayTaskMap.get(apk + day + "exectotal");
						if (execTotal != null) {
							int tempExecTotal = execTotal.getExecTotal() + resultInfo.getExecTotal();
							resultInfo.setExecTotal(tempExecTotal);
						}
						resultInfo.setDay(day);
						resultInfo.setMark(apk);
						result.put(outKey, resultInfo);
					}
				}
			}
		} catch (ParseException e) {
			LOGGER.error("查询失败", e);
		}
		return result;
	}



	private List<ApkTaskInfo> thirdLoginTaskInfoList(String[] days, List<MarkDayTask> taskList) {
		List<ApkTaskInfo> currList = new ArrayList<ApkTaskInfo>();
		if (taskList != null && taskList.size() > 0) {
			ChannelApkConfig config = channelApkInfoService.selectChannelApkConfig(taskList.get(0).getMark());
			if (config == null) {
				return currList;
			}
			for (MarkDayTask task : taskList) {
				for (String day : days) {
					String taskDay = task.getDay();
					if (taskDay.equals(day)) {
						ApkTaskInfo taskInfo = new ApkTaskInfo();
						taskInfo.setTotal(config.getDaylimit());
						taskInfo.setExecTotal(task.getTaskNum());
						taskInfo.setApkName(config.getApkName());
						taskInfo.setMark(config.getMark());
						taskInfo.setDay(task.getDay());
						currList.add(taskInfo);
					}
				}
			}
		}
		return currList;
	}

	private List<ApkTaskInfo> thirdLoginTaskInfoList(String[] days) {
		List<ApkTaskInfo> currList = new ArrayList<ApkTaskInfo>();

		List<ApkTaskInfo> weiboList = thirdLoginTaskInfoList(days, weiboUserService.selectRetentTaskList());
		if (weiboList != null && weiboList.size() > 0) {
			currList.addAll(weiboList);
		}
		return currList;
	}

	@SuppressWarnings("unchecked")
	@Override
	public List<ApkTaskInfo> selectCountNewTask(TaskQueryVo queryVo) {
		String mark = queryVo.getMark();
		String start = queryVo.getStart();
		String end = queryVo.getEnd();
		if (StringUtils.isBlank(mark)) {
			queryVo.setMark(null);
		}
		if (StringUtils.isBlank(start)) {
			start = DateUtil.getCurrentDateStr();
		} else {
			start = start.replaceAll("-", "");
		}
		if (StringUtils.isBlank(end)) {
			end = DateUtil.getCurrentDateStr();
		} else {
			end = end.replaceAll("-", "");
		}
		ChannelApkConfig apkConfig = new ApkRetentConfig();
		if (StringUtils.isNotBlank(mark)) {
			apkConfig.setMark(mark);
		}
		List<ChannelApkConfig> apkList = channelApkInfoService.queryApkList(apkConfig);
		if (apkList == null || apkList.size() == 0) {
			return new ArrayList();
		}
		Set<String> set = new HashSet();
		for (ChannelApkConfig config : apkList) {
			set.add(config.getMark());
		}
		Set<String> daySet = DateUtil.getDatesBetweenTwoDate(start, end);
		String[] days = daySet.toArray(new String[0]);
		List<ApkTaskInfo> resultList = thirdLoginTaskInfoList(days);
		Iterator<ApkTaskInfo> iterator = resultList.iterator();
		while (iterator.hasNext()) {
			ApkTaskInfo taskInfo = iterator.next();
			if (!set.contains(taskInfo.getMark())) {
				iterator.remove();
			}
		}
		for (String day : days) {
			try {
				queryVo.setCurrentDate(day);
				List<ApkTaskInfo> currList = dmChannelRetentDAO.selectCountNewTask(queryVo);
				List<ApkTaskInfo> readNewTaskPayList = dmChannelRetentDAO.selectReadNewTaskPay(queryVo);
				for (ApkTaskInfo taskInfo : currList) {
					String mark1 = taskInfo.getMark();
					if (!set.contains(mark1)) {
						continue;
					}
					// 只有目前阅读才有支付数据
					for (ApkTaskInfo readNewTaskInfo : readNewTaskPayList) {
						if (mark1.equals(readNewTaskInfo.getMark())) {
							taskInfo.setPayNum(readNewTaskInfo.getPayNum());
							if (taskInfo.getExecTotal() > 0) {
								BigDecimal b = new BigDecimal((double) readNewTaskInfo.getPayNum() / taskInfo.getExecTotal());
								taskInfo.setPayratio(b.setScale(4, BigDecimal.ROUND_HALF_UP).doubleValue());
							} else {
								taskInfo.setPayratio(0d);
							}
						}
					}
					try {
						ChannelApkConfig config = channelApkInfoService.selectChannelApkConfig(mark1);
						taskInfo.setDay(day);
						taskInfo.setTotal(config.getDaylimit());
						taskInfo.setApkName(config.getApkName());
						resultList.add(taskInfo);
					} catch (Exception e) {
						LOGGER.error("对应的mark【{}】没有", mark1, e);
					}
				}
			} catch (Exception e) {
				LOGGER.error("留存表【{}】不存在", day, e);
			}
		}
		sort(resultList, queryVo);
		return resultList;
	}

	/**
	 *
	 * 按已执行量、手机占比，默认排序进行排序
	 *
	 * @author <a href="mailto:zhouchao@xingbook.com" >周超</a>
	 * @param resultList
	 * @param queryVo
	 */
	private void sort(List<ApkTaskInfo> resultList, TaskQueryVo queryVo) {
		String sort = queryVo.getSort();
		String order = queryVo.getOrder();

		Comparator<ApkTaskInfo> comparator = sortMap.get(sort + "_" + order);
		if (comparator == null) {
			Collections.sort(resultList, new ApkTaskInfoComparator());
			return;
		}

		Collections.sort(resultList, comparator);
	}

	@SuppressWarnings("rawtypes")
	class ApkTaskInfoComparator implements Comparator {

		@Override
		public int compare(Object o1, Object o2) {
			if (o1 == null || o2 == null) {
				return -1;
			} else if (!(o1 instanceof ApkTaskInfo) || !(o2 instanceof ApkTaskInfo)) {
				return -1;
			}
			ApkTaskInfo taskInfo1 = (ApkTaskInfo) o1;
			ApkTaskInfo taskInfo2 = (ApkTaskInfo) o2;
			String targetDay1 = taskInfo1.getDay();
			String targetDay2 = taskInfo2.getDay();
			if (StringUtils.isBlank(targetDay1) || StringUtils.isBlank(targetDay2)) {
				return -1;
			}
			return targetDay1.compareTo(targetDay2);
		}

	}

	class ExecRateAscComparator implements Comparator<ApkTaskInfo> {
		@Override
		public int compare(ApkTaskInfo arg0, ApkTaskInfo arg1) {
			return commonCompare(arg0.getExecRate(), arg1.getExecRate());
		}
	}

	class ExecRateDescComparator implements Comparator<ApkTaskInfo> {
		@Override
		public int compare(ApkTaskInfo arg0, ApkTaskInfo arg1) {
			return commonCompare(arg1.getExecRate(), arg0.getExecRate());
		}
	}

	class MobileRateAscComparator implements Comparator<ApkTaskInfo> {
		@Override
		public int compare(ApkTaskInfo arg0, ApkTaskInfo arg1) {
			return commonCompare(arg0.getMobileRate(), arg1.getMobileRate());
		}
	}

	class MobileRateDescComparator implements Comparator<ApkTaskInfo> {
		@Override
		public int compare(ApkTaskInfo arg0, ApkTaskInfo arg1) {
			return commonCompare(arg1.getMobileRate(), arg0.getMobileRate());
		}
	}


	private int commonCompare(Double data1, Double data2) {
		if (data1 == null) {
			data1 = 0D;
		}
		if (data2 == null) {
			data2 = 0D;
		}

		if (data1 == data2) {
			return 0;
		}

		if (data1 > data2) {
			return 1;
		}
		return -1;
	}

}
